home *** CD-ROM | disk | FTP | other *** search
- /* Expire old news articles */
-
- /* Written by Bernie Roehl, May 1990 */
-
- /* Works with the NNTPCLI by Anders Klemets and Bernie Roehl */
-
- /* Two possible uses:
-
- EXPIRE filename [n,m,o]
-
- will expire only the give file. If n,m,o are given, they specify the
- number of kilobytes, articles, and days; those which are zero are taken
- as unrestricted.
-
- EXPIRE directory [n,m,o [controlfile]]
-
- will expire all the .txt files under the given directory and all its
- subdirectories, recursively. The n,m,o parameter is the default set
- of values as described above; these may be overridden by entries in
- the controlfile, which are of the form
-
- filename n,m,o
-
- where 'filename' is the name of the .txt file containing the articles
- and n,m,o are the values to override the defaults (on this file only).
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <dir.h>
- #include <dos.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- #include <sys/timeb.h>
- #include <string.h>
- #include <ctype.h>
- #include <time.h>
-
- char *progname = "EXPIRE";
-
- /* Default expiry values: */
-
- int def_kilos = 32; /* 32 kilobytes/group */
- int def_arts = 500; /* 500 articles/group */
- int def_days = 7; /* 7 days from arrival date */
-
- void main(argc, argv)
- int argc;
- char *argv[];
- {
- struct stat statbuf;
- void expire(), walk_dirs();
- if (argc < 2) {
- printf("%s: Correct usage is 'expire path [n,m,o [controlfile]]'\n", progname);
- exit(2);
- }
- if (stat(argv[1], &statbuf)) {
- printf("%s: Couldn't stat '%s'\n", progname, argv[1]);
- exit(3);
- }
- if (argc > 2)
- if (sscanf(argv[2], "%d,%d,%d", &def_kilos, &def_arts, &def_days) != 3) {
- printf("%s: Syntax error in second argument (\"%s\")\n", progname, argv[2]);
- exit(4);
- }
- if (statbuf.st_mode & S_IFREG)
- expire(argv[1], def_kilos, def_arts, def_days);
- else if (argc > 3) {
- FILE *ctl;
- if ((ctl = fopen(argv[3], "r")) == NULL) {
- printf("%s: Could not open control file '%s'\n", progname, argv[3]);
- exit(5);
- }
- walk_dirs(argv[1], ctl);
- fclose(ctl);
- }
- else
- walk_dirs(argv[1], NULL);
- }
-
- void expire(char *filename, int kilos, int arts, int days)
- {
- char buff[80], dir[80], *p, *q, *d;
- FILE *ng;
- long lowater;
- strcpy(dir, filename);
- if ((p = strrchr(dir, '\\')) != NULL) {
- *p++ = '\0';
- d = dir;
- }
- else {
- p = dir;
- d = ".";
- }
- if ((q = strchr(p, '.')) != NULL)
- *q = '\0';
- if (mlock(d, p)) {
- printf("%s: Couldn't get lock on '%s'\n", progname, filename);
- return;
- }
- if ((ng = fopen(filename, "r")) == NULL) {
- printf("%s: Couldn't open '%s'\n", progname, filename);
- rmlock(d, p);
- return;
- }
- lowater = 0L;
- if (kilos) {
- long pos;
- fseek(ng, 0L, SEEK_END);
- if (ftell(ng) > kilos * 1024L) { /* File larger than limit? */
- fseek(ng, -kilos * 1024L, SEEK_END);
- for (pos = ftell(ng); fgets(buff, sizeof(buff), ng); pos = ftell(ng))
- if (!strnicmp(buff, "From ", 5))
- break;
- if (pos > lowater)
- lowater = pos;
- }
- }
- if (arts) {
- long pos;
- int nart = 0;
- rewind(ng);
- while (fgets(buff, sizeof(buff), ng)) /* count up the articles */
- if (!strnicmp(buff, "From ", 5))
- ++nart;
- if (nart > arts) {
- nart -= arts; /* nart is now the number of articles to delete */
- rewind(ng);
- for (pos = ftell(ng); fgets(buff, sizeof(buff), ng); pos = ftell(ng))
- if (!strnicmp(buff, "From ", 5))
- if (--nart < 0)
- break;
- if (pos > lowater)
- lowater = pos;
- }
- }
- if (days) {
- long pos;
- rewind(ng);
- for (pos = ftell(ng); fgets(buff, sizeof(buff), ng); pos = ftell(ng))
- if (!strnicmp(buff, "From ", 5)) {
- char *p;
- struct timeb t;
- long now, then;
- if ((p = strrchr(buff, ' ')) == NULL) /* weird format... no blanks! */
- continue;
- if (!isdigit(*++p)) /* missing or invalid timestamp */
- continue;
- then = atol(p);
- ftime(&t);
- now = t.time;
- if ((now - then) > (days * 24L * 60L * 60L)) {
- if (pos > lowater)
- lowater = pos;
- }
- }
- }
- if (lowater > 0L) {
- FILE *tmpf;
- char tfile[80];
- sprintf(tfile, "%s/%s.tmp", d, p);
- unlink(tfile);
- if ((tmpf = fopen(tfile, "w")) == NULL) {
- printf("%s: Could not create '%s'\n", progname, tfile);
- fclose(ng);
- rmlock(d, p);
- return;
- }
- fseek(ng, lowater, SEEK_SET);
- while (fgets(buff, sizeof(buff), ng))
- fputs(buff, tmpf);
- fclose(tmpf);
- fclose(ng);
- sprintf(buff, "%s/%s.txt", d, p);
- unlink(buff);
- rename(tfile, buff);
- }
- else
- fclose(ng);
- rmlock(d, p);
- }
-
- void walk_dirs(char *dir, FILE *ctl)
- {
- char work[80];
- struct ffblk ff;
-
- sprintf(work, "%s/*.txt", dir);
- if (findfirst(work, &ff, 0) == 0)
- do {
- int kilos, arts, days;
- char input_line[100];
- kilos = def_kilos; arts = def_arts; days = def_days;
- sprintf(work, "%s/%s", dir, ff.ff_name);
- if (ctl) {
- int lineno;
- rewind(ctl);
- for (lineno = 1; fgets(input_line, sizeof(input_line), ctl); ++lineno) {
- char *p;
- if ((p = strchr(input_line, '\n')) != NULL)
- *p = '\0';
- if ((p = strchr(input_line, '#')) != NULL)
- *p = '\0';
- if ((p = strtok(input_line, " \t")) == NULL)
- continue;
- if (!strnicmp(p, work, strlen(work))) {
- if ((p = strtok(NULL, " \t")) == NULL)
- continue;
- if (sscanf(p, "%d,%d,%d", &kilos, &arts, &days) != 3)
- printf("%s: invalid syntax in line %d of control file\n", progname, lineno);
- }
- }
- }
- expire(work, kilos, arts, days);
- } while (findnext(&ff) == 0);
-
- sprintf(work, "%s/*.*", dir);
- if (findfirst(work, &ff, FA_DIREC) == 0)
- do {
- if (ff.ff_name[0] != '.') {
- sprintf(work, "%s/%s", dir, ff.ff_name);
- walk_dirs(work, ctl);
- }
- } while(findnext(&ff) == 0);
- }
-
- mlock(char *dir, char *id) /* from KA9Q */
- {
- char lockname[80];
- int fd;
-
- /* Try to create the lock file in an atomic operation */
- sprintf(lockname,"%s/%s.lck",dir,id);
- #ifdef AMIGA
- /* don't ask, really, just don't ask... I'd do file locking on
- * an Amiga much more differently than this.
- */
- if(access(lockname, 0) == 0)
- return -1;
- #endif
- if((fd = open(lockname, O_WRONLY|O_EXCL|O_CREAT,0600)) == -1)
- return -1;
- close(fd);
- return 0;
- }
-
- rmlock(char *dir, char *id) /* from KA9Q */
- {
- char lockname[80];
- sprintf(lockname,"%s/%s.lck",dir,id);
- return(unlink(lockname));
- }
-
-